Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Node / ReticulumProjects / MeshChatX.git / files / tests / e2e / browser-permissions.spec.js

Displaying Raw • Download


tests/e2e/browser-permissions.spec.js 8db1f550262ba40ef35b4f081dfd893e78dc1658 (8db1f550) Text, 8.95 KB

T8b949e// SPDX-License-Identifier: 0BSD

Tff7b72const Tb4b4b4{ Te6edf3testTb4b4b4, Te6edf3expect Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"@playwright/test"Tb4b4b4)Tb4b4b4;
Tff7b72const Tb4b4b4{ Te6edf3E2E_BACKEND_ORIGINTb4b4b4, Te6edf3prepareE2eSession Tb4b4b4} Tff7b72= Te6edf3requireTb4b4b4(Ta5d6ff"./helpers"Tb4b4b4)Tb4b4b4;

T8b949e/**
* Browser permission / chooser regressions for Calls mic and RNode Bluetooth.
* Real OS prompts cannot be driven reliably in CI, so these tests install
* controlled navigator.mediaDevices / navigator.bluetooth shims and assert the
* product code asks the browser the right way.
*/

Tff7b72async Tff7b72function Te6edf3installMicProbeTb4b4b4(Te6edf3pageTb4b4b4, Tb4b4b4{ Te6edf3secure Tff7b72= Tff7b72true Tb4b4b4} Tff7b72= Tb4b4b4{Tb4b4b4}Tb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3addInitScriptTb4b4b4(Tb4b4b4(Te6edf3isSecureTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Tffa657windowTb4b4b4, Ta5d6ff"isSecureContext"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3getTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Te6edf3isSecureTb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCalls Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tff7b72const Te6edf3stop Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3fakeStream Tff7b72= Tb4b4b4{
Te6edf3getTracksTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Tb4b4b4[Tb4b4b4{ Te6edf3stopTb4b4b4, Te6edf3kindTff7b72: Ta5d6ff"audio"Tb4b4b4, Te6edf3stopTrackTff7b72: Te6edf3stop Tb4b4b4}Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3getUserMedia Tff7b72= Tff7b72async Tb4b4b4(Te6edf3constraintsTb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCallsTb4b4b4.Te6edf3pushTb4b4b4(Te6edf3constraintsTb4b4b4)Tb4b4b4;
Tff7b72return Te6edf3fakeStreamTb4b4b4;
Tb4b4b4}Tb4b4b4;
Tff7b72const Te6edf3enumerateDevices Tff7b72= Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4[
Tb4b4b4{ Te6edf3kindTff7b72: Ta5d6ff"audioinput"Tb4b4b4, Te6edf3deviceIdTff7b72: Ta5d6ff"mic-1"Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff"Fake Mic"Tb4b4b4, Te6edf3groupIdTff7b72: Ta5d6ff"g1" Tb4b4b4}Tb4b4b4,
Tb4b4b4{ Te6edf3kindTff7b72: Ta5d6ff"audiooutput"Tb4b4b4, Te6edf3deviceIdTff7b72: Ta5d6ff"spk-1"Tb4b4b4, Te6edf3labelTff7b72: Ta5d6ff"Fake Speaker"Tb4b4b4, Te6edf3groupIdTff7b72: Ta5d6ff"g1" Tb4b4b4}Tb4b4b4,
Tb4b4b4]Tb4b4b4;
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"mediaDevices"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3valueTff7b72: Tb4b4b4{ Te6edf3getUserMediaTb4b4b4, Te6edf3enumerateDevices Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4, Te6edf3secureTb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3enableWebAudioBridgeTb4b4b4(Te6edf3pageTb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3pageTb4b4b4.Tff7b72gotoTb4b4b4(Ta5d6ff"/#/call"Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff"Phone"Tb4b4b4, Te6edf3exactTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{ Te6edf3timeoutTff7b72: T79c0ff30000 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3refresh Tff7b72= Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff"Refresh Devices"Tb4b4b4, Te6edf3exactTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(
Tb4b4b4(Tff7b72await Te6edf3refreshTb4b4b4.Te6edf3countTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72=== T79c0ff0 Tff7b72||
Tff7b72!Tb4b4b4(Tff7b72await Te6edf3refresh
Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tb4b4b4.Te6edf3isVisibleTb4b4b4(Tb4b4b4)
Tb4b4b4.Tff7b72catchTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72falseTb4b4b4)Tb4b4b4)
Tb4b4b4) Tb4b4b4{
Tff7b72const Te6edf3label Tff7b72= Te6edf3pageTb4b4b4.Te6edf3locatorTb4b4b4(Ta5d6ff'label[for="web-audio-toggle"]'Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3labelTb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{ Te6edf3timeoutTff7b72: T79c0ff20000 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3input Tff7b72= Te6edf3pageTb4b4b4.Te6edf3locatorTb4b4b4(Ta5d6ff"#web-audio-toggle"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3checked Tff7b72= Tff7b72await Te6edf3inputTb4b4b4.Te6edf3isCheckedTb4b4b4(Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3disabled Tff7b72= Tff7b72await Te6edf3inputTb4b4b4.Te6edf3isDisabledTb4b4b4(Tb4b4b4)Tb4b4b4.Tff7b72catchTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72falseTb4b4b4)Tb4b4b4;
Tff7b72if Tb4b4b4(Tff7b72!Te6edf3checked Tff7b72&& Tff7b72!Te6edf3disabledTb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3labelTb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3refreshTb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{ Te6edf3timeoutTff7b72: T79c0ff15000 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Tff7b72async Tff7b72function Te6edf3dismissViteOverlayTb4b4b4(Te6edf3pageTb4b4b4) Tb4b4b4{
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657documentTb4b4b4.Te6edf3querySelectorAllTb4b4b4(Ta5d6ff"vite-error-overlay"Tb4b4b4)Tb4b4b4.Te6edf3forEachTb4b4b4(Tb4b4b4(Te6edf3elTb4b4b4) Tb4b4b4=> Te6edf3elTb4b4b4.Te6edf3removeTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}

Te6edf3testTb4b4b4.Te6edf3describeTb4b4b4(Ta5d6ff"Browser mic permission prompt path"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3testTb4b4b4.Te6edf3beforeEachTb4b4b4(Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3request Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72await Te6edf3prepareE2eSessionTb4b4b4(Te6edf3requestTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3testTb4b4b4(Ta5d6ff"Refresh Devices prompts getUserMedia with bare audio first"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3page Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72await Te6edf3installMicProbeTb4b4b4(Te6edf3pageTb4b4b4, Tb4b4b4{ Te6edf3secureTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3enableWebAudioBridgeTb4b4b4(Te6edf3pageTb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCalls Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff"Refresh Devices"Tb4b4b4, Te6edf3exactTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4.Te6edf3pollTb4b4b4(Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCallsTb4b4b4.Te6edf3lengthTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeGreaterThanTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3calls Tff7b72= Tff7b72await Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCallsTb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3callsTb4b4b4[T79c0ff0Tb4b4b4]Tb4b4b4)Tb4b4b4.Te6edf3toEqualTb4b4b4(Tb4b4b4{ Te6edf3audioTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3testTb4b4b4(Ta5d6ff"Refresh Devices refuses insecure contexts without calling getUserMedia"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3page Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72await Te6edf3installMicProbeTb4b4b4(Te6edf3pageTb4b4b4, Tb4b4b4{ Te6edf3secureTff7b72: Tff7b72false Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3enableWebAudioBridgeTb4b4b4(Te6edf3pageTb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCalls Tff7b72= Tb4b4b4[Tb4b4b4]Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff"Refresh Devices"Tb4b4b4, Te6edf3exactTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3pageTb4b4b4.Te6edf3getByTextTb4b4b4(Ta5d6ff/Microphone access needs HTTPS|secure URL/iTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{
Te6edf3timeoutTff7b72: T79c0ff10000Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3calls Tff7b72= Tff7b72await Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tffa657windowTb4b4b4.Te6edf3__meshchatxGumCallsTb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3callsTb4b4b4)Tb4b4b4.Te6edf3toEqualTb4b4b4(Tb4b4b4[Tb4b4b4]Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3testTb4b4b4.Te6edf3describeTb4b4b4(Ta5d6ff"RNode flasher Web Bluetooth chooser path"Tb4b4b4, Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Te6edf3testTb4b4b4.Te6edf3beforeEachTb4b4b4(Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3request Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72await Te6edf3prepareE2eSessionTb4b4b4(Te6edf3requestTb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3testTb4b4b4(Ta5d6ff"Brave without Web Bluetooth shows Try Bluetooth and flag guidance"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3page Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3addInitScriptTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Tffa657windowTb4b4b4, Ta5d6ff"isSecureContext"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3getTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"userAgent"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3getTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Ta5d6ff"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Brave/1.70 Chrome/120.0.0.0 Safari/537.36"Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"brave"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3valueTff7b72: Tb4b4b4{ Te6edf3isBraveTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72true Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72delete Te6edf3navigatorTb4b4b4.Te6edf3bluetoothTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4{
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"bluetooth"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3valueTff7b72: Tff7b72undefinedTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Tff7b72gotoTb4b4b4(Ta5d6ff"/#/tools/rnode-flasher"Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3pageTb4b4b4.Te6edf3getByTextTb4b4b4(Ta5d6ff"Bluetooth is unavailable"Tb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{ Te6edf3timeoutTff7b72: T79c0ff30000 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3pageTb4b4b4.Te6edf3getByTextTb4b4b4(Ta5d6ff/brave:\/\/flags\/#brave-web-bluetooth-api/iTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3dismissViteOverlayTb4b4b4(Te6edf3pageTb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3tryBtn Tff7b72= Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff/Try Bluetooth/i Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3recheckBtn Tff7b72= Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff/Recheck Bluetooth/i Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3tryBtnTb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3recheckBtnTb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3tryBtnTb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4{ Te6edf3forceTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3pageTb4b4b4.Te6edf3getByTextTb4b4b4(Ta5d6ff/Brave disables Web Bluetooth|brave:\/\/flags/iTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{
Te6edf3timeoutTff7b72: T79c0ff10000Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3testTb4b4b4(Ta5d6ff"Try Bluetooth calls requestDevice when Web Bluetooth becomes available"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3page Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3addInitScriptTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Tffa657windowTb4b4b4, Ta5d6ff"isSecureContext"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3getTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Tff7b72trueTb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"userAgent"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3getTb4b4b4(Tb4b4b4) Tb4b4b4{
Tff7b72return Ta5d6ff"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 Brave/1.70 Chrome/120.0.0.0 Safari/537.36"Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"brave"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3valueTff7b72: Tb4b4b4{ Te6edf3isBraveTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72true Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72try Tb4b4b4{
Tff7b72delete Te6edf3navigatorTb4b4b4.Te6edf3bluetoothTb4b4b4;
Tb4b4b4} Tff7b72catch Tb4b4b4{
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"bluetooth"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3valueTff7b72: Tff7b72undefinedTb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}
Tffa657windowTb4b4b4.Te6edf3__meshchatxBtRequests Tff7b72= T79c0ff0Tb4b4b4;
Tffa657windowTb4b4b4.Te6edf3__meshchatxInstallBluetooth Tff7b72= Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657ObjectTb4b4b4.Te6edf3definePropertyTb4b4b4(Te6edf3navigatorTb4b4b4, Ta5d6ff"bluetooth"Tb4b4b4, Tb4b4b4{
Te6edf3configurableTff7b72: Tff7b72trueTb4b4b4,
Te6edf3valueTff7b72: Tb4b4b4{
Te6edf3requestDeviceTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tffa657windowTb4b4b4.Te6edf3__meshchatxBtRequests Tff7b72+= T79c0ff1Tb4b4b4;
Tff7b72return Tb4b4b4{
Te6edf3gattTff7b72: Tb4b4b4{
Te6edf3connectedTff7b72: Tff7b72falseTb4b4b4,
Te6edf3disconnectTb4b4b4(Tb4b4b4) Tb4b4b4{Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4,
Te6edf3getAvailabilityTff7b72: Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tff7b72trueTb4b4b4,
Tb4b4b4}Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Tff7b72gotoTb4b4b4(Ta5d6ff"/#/tools/rnode-flasher"Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3tryBtn Tff7b72= Te6edf3pageTb4b4b4.Te6edf3getByRoleTb4b4b4(Ta5d6ff"button"Tb4b4b4, Tb4b4b4{ Te6edf3nameTff7b72: Ta5d6ff/Try Bluetooth/i Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(Te6edf3tryBtnTb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{ Te6edf3timeoutTff7b72: T79c0ff30000 Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3dismissViteOverlayTb4b4b4(Te6edf3pageTb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tffa657windowTb4b4b4.Te6edf3__meshchatxInstallBluetoothTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3tryBtnTb4b4b4.Te6edf3clickTb4b4b4(Tb4b4b4{ Te6edf3forceTff7b72: Tff7b72true Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4.Te6edf3pollTb4b4b4(Tff7b72async Tb4b4b4(Tb4b4b4) Tb4b4b4=> Te6edf3pageTb4b4b4.Te6edf3evaluateTb4b4b4(Tb4b4b4(Tb4b4b4) Tb4b4b4=> Tffa657windowTb4b4b4.Te6edf3__meshchatxBtRequestsTb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeGreaterThanTb4b4b4(T79c0ff0Tb4b4b4)Tb4b4b4;
Tff7b72await Te6edf3expectTb4b4b4(
Te6edf3pageTb4b4b4.Te6edf3getByTextTb4b4b4(Ta5d6ff/Bluetooth device chooser worked|Bluetooth transport is ready/iTb4b4b4)Tb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)
Tb4b4b4)Tb4b4b4.Te6edf3toBeVisibleTb4b4b4(Tb4b4b4{
Te6edf3timeoutTff7b72: T79c0ff10000Tb4b4b4,
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;

Te6edf3testTb4b4b4(Ta5d6ff"Permissions-Policy from backend allows bluetooth for flasher origin"Tb4b4b4, Tff7b72async Tb4b4b4(Tb4b4b4{ Te6edf3request Tb4b4b4}Tb4b4b4) Tb4b4b4=> Tb4b4b4{
Tff7b72const Te6edf3index Tff7b72= Tff7b72await Te6edf3requestTb4b4b4.Te6edf3getTb4b4b4(Ta5d6ff`Tffd700${Te6edf3E2E_BACKEND_ORIGINTffd700}Ta5d6ff/Ta5d6ff`Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3indexTb4b4b4.Te6edf3okTb4b4b4(Tb4b4b4)Tb4b4b4)Tb4b4b4.Te6edf3toBeTruthyTb4b4b4(Tb4b4b4)Tb4b4b4;
Tff7b72const Te6edf3policy Tff7b72= Te6edf3indexTb4b4b4.Te6edf3headersTb4b4b4(Tb4b4b4)Tb4b4b4[Ta5d6ff"permissions-policy"Tb4b4b4] Tff7b72|| Ta5d6ff""Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3policyTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"bluetooth=(self)"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3policyTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"microphone=(self)"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3policyTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"serial=(self)"Tb4b4b4)Tb4b4b4;
Te6edf3expectTb4b4b4(Te6edf3policyTb4b4b4)Tb4b4b4.Te6edf3toContainTb4b4b4(Ta5d6ff"usb=(self)"Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;
Tb4b4b4}Tb4b4b4)Tb4b4b4;


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────